package api

import (
	"oc_saas/internal/glo"
	oc_types "oc_saas/internal/types"
	"oc_saas/internal/utils"

	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// 数据绑定的形式
const (
	_ int = iota //递增
	JSON
	QUERY
	XML
	YAML
	URI
)

type Api struct {
	Context *gin.Context        //路由上下文
	Claims  *utils.CustomClaims //校验信息
	Orm     *gorm.DB            //orm
	Errors  error               //错误
}

// 获取上下文
func (a *Api) MakeContext(c *gin.Context) *Api {
	a.Context = c
	return a
}

// 是否需要绑定结构体
func (a *Api) Bind(d interface{}, bind int) *Api {
	var err error
	switch bind {
	case JSON:
		err = a.Context.ShouldBindJSON(d)
	case QUERY:
		err = a.Context.ShouldBindQuery(d)
	case XML:
		err = a.Context.ShouldBindXML(d)
	case YAML:
		err = a.Context.ShouldBindYAML(d)
	case URI:
		err = a.Context.ShouldBindUri(d)
	}
	a.Errors = err
	return a
}

// 表单校验
func (a *Api) Valid(d interface{}) *Api {
	a.Errors = glo.OC_VALID.Struct(d)
	return a
}

// 选择ORM
func (a *Api) MakeOrm(funcs ...func(c *gin.Context) *gorm.DB) *Api {
	if len(funcs) == 1 {
		a.Orm = funcs[0](a.Context) //自定义函数设置orm
	} else {
		// 解析token内容
		token := a.Context.Request.Header.Get("x-token")
		if token != "" {
			j := new(utils.JWTAuth)
			if customClaims, err := j.ParseToken(token); err != nil {
				a.Errors = err
			} else {
				a.Claims = customClaims
				if customClaims.Domain != "" && customClaims.DbName != "" {
					a.Orm = glo.OC_ORM_CLUSTER[customClaims.Domain+"/"+customClaims.DbName]
				} else {
					a.Orm = glo.OC_DB
				}
			}
		} else {
			a.Orm = glo.OC_DB
		}
	}
	return a
}

// 选择Service
func (a *Api) MakeService(s *Service) *Api {
	s.Orm = a.Orm
	s.Error = a.Errors
	return a
}

func (a *Api) Ok(c *gin.Context) {
	oc_types.Response(200, oc_types.ResBody{Code: oc_types.SUCCESS, Msg: "成功", Data: map[string]interface{}{}}, c)
}
func (a *Api) OkWidthMessage(msg string, c *gin.Context) {
	oc_types.Response(200, oc_types.ResBody{Code: oc_types.SUCCESS, Msg: msg, Data: map[string]interface{}{}}, c)
}
func (a *Api) OkWithData(data interface{}, c *gin.Context) {
	oc_types.Response(200, oc_types.ResBody{Data: data, Msg: "成功"}, c)
}
func (a *Api) Fail(c *gin.Context) {
	oc_types.Response(200, oc_types.ResBody{Code: oc_types.FAIL, Msg: "失败", Data: map[string]interface{}{}}, c)
}
func (a *Api) FailWithMessage(msg string, c *gin.Context) {
	oc_types.Response(200, oc_types.ResBody{Code: oc_types.FAIL, Msg: msg, Data: map[string]interface{}{}}, c)
}
